package org.yagnus.stats.sampler.discrete;

import org.yagnus.stats.sampler.Sampler;

/**
 * 
 * @author hc.busy
 * 
 * @param <BASETYPE>
 */
public abstract class ArraySampler<BASETYPE> extends Sampler {

    protected abstract void _init(BASETYPE[] t, double[] weights);

    /**
     * This function constructs a sampler from specified array and corresponding weights
     * 
     * @param t
     *            the sampmle spae
     * @param weights
     *            the weights corresponding to each item
     * @return
     */

    public ArraySampler(BASETYPE[] t, double[] weights) {
        super();
        _init(t, weights);
    }

    public ArraySampler(BASETYPE[] t, long[] weights) {
        super();
        double[] w2 = new double[weights.length];
        for (int i = 0; i < weights.length; ++i) {
            w2[i] = (double) weights[i];
        }
        _init(t, w2);
    }

    public ArraySampler(BASETYPE[] t, int[] weights) {
        super();
        double[] w2 = new double[weights.length];
        for (int i = 0; i < weights.length; ++i) {
            w2[i] = (double) weights[i];
        }
        _init(t, w2);
    }

    public ArraySampler(BASETYPE[] t) {
        super();
        double[] w2 = new double[t.length];
        for (int i = 0; i < w2.length; ++i) {
            w2[i] = 1d;
        }
        _init(t, w2);
    }

    /**
     * 
     * this function modifies the sampling problem to add to the sample space
     * 
     * @param t
     *            the new member of the population
     * @param w
     *            its weight.
     */
    public abstract void addSample(BASETYPE t, double w);

    public void addSamples(BASETYPE[] t, double[] w) {
        if (t.length != w.length) {
            throw new IllegalArgumentException("Sample and weights do not have same lengths");
        }
        for (int i = 0; i < t.length; ++i) {
            addSample(t[i], w[i]);
        }
    }

    /**
     * Removes all instances of the object t from sample space
     * 
     * @param t
     *            the the sample to remove
     */
    public abstract void removeSample(BASETYPE t);

    public void removeSamples(BASETYPE[] t) {
        for (int i = 0; i < t.length; ++i) {
            removeSample(t[i]);
        }
    }

}
